package com.hubu.tree;

import com.hubu.tree.util.Comparator;
import com.hubu.tree.util.Visitor;

 public  abstract  class AbstractTree<T> implements Tree<T> {
    protected  int size;
    protected Comparator<T> comparator;

    protected Visitor<T> visitor;

    protected TreeNode<T> root;

    public AbstractTree(Comparator<T> comparator,Visitor<T> visitor){
        this.comparator=comparator;
        this.visitor=visitor;
    }
    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size==0;
    }

    @Override
    public void clear() {

    }




    @Override
    public void preOrder() {
        if(root!=null){
            preOrder(root);
        }
    }
    public void preOrder(TreeNode<T> node){
        if(node==null) return ;
        System.out.println(node.getValue());
        preOrder(node.leftOf());
        preOrder(node.rightOf());
    }

    @Override
    public void inOrder() {
        if(root!=null) inOrder(root);
    }


     public void inOrder(TreeNode<T> node) {
         if(node==null) return ;
         inOrder(node.leftOf());
         System.out.println(node.getValue());
         inOrder(node.rightOf());
     }


     @Override
    public void postOrder() {

    }

    @Override
    public void levelOrder() {

    }

    public int compare(T value1,T value2){
        return comparator!=null?comparator.compare(value1,value2):((Comparable)value1).compareTo(value2);
    }

    @Override
    public int height() {
        return 0;
    }
    public TreeNode<T> createNode(T value,TreeNode<T> left,TreeNode<T> right){
        TreeNode<T> node=new Node<>(value,left,right);
        return node;
    }
    public static class Node<T> implements TreeNode<T>{

        protected T value;

        protected TreeNode<T> left;


        protected TreeNode<T> right;

        public Node(T value,TreeNode<T> left,TreeNode<T> right){
            this.value=value;
            this.left=left;
            this.right=right;
        }


        @Override
        public T getValue() {
            return value;
        }

        @Override
        public TreeNode<T> leftOf() {
            return left;
        }

        @Override
        public TreeNode<T> rightOf() {
            return right;
        }

        @Override
        public T setValue(T value) {
            T oldValue=this.value;
            this.value=value;
            return oldValue;
        }

        @Override
        public void setLeft(TreeNode<T> left) {
            this.left=left;
        }

        @Override
        public void setRight(TreeNode<T> right) {
            this.right=right;
        }
    }

}
